﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "SaveFileAsCmd.h"
#include "SaveFileCmd.h"
#include "OpenFileCmd.h"
#include "IDocument.h"
#include "IUiDocumentViewManager.h"
#include "IUiDocument.h"
#include "IUiView.h"
#include "UiCommonDialog.h"
#include "GbmpUiPlatformCommandIds.h"
#include "IAction.h"
#include "IActionManager.h"
#include "IActionManager.h"
#include "FilePath.h"
#include "IDocumentManager.h"
#include "IFileExtensions.h"
#include "GbmpFileSystem.h"
#include "IUserTransaction.h"
#include "GbmpUiPlatformCommandRegister.h"
#include "DocumentSaveError.h"
#include "UiNotificationUtils.h"
#include "DocumentValidationUtils.h"
#include "CommandParameters.h"
#include "GcmpCommandState.h"
#include "GcmpModel.h"
#include "GcmpDatabase.h"
#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"

using namespace gcmp;

EXPOSE_DEBUG_MODE_EXPORT(RemoveReadonlyWithNoTransactionAndNoSave, GCMP_DATABASE_EXPORT);
EXPOSE_DEBUG_MODE_EXPORT(EnableFixInvalidDoc, GCMP_MODEL_EXPORT);

gcmp::OwnerPtr<IAction> SaveFileAsCmd::ExecuteCommand(const gcmp::CommandParameters& cmdParams)
{
    IUiDocumentViewManager* pUiDocViewMgr = IUiDocumentViewManager::Get();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pUiDocViewMgr, L"pUiDocViewMgr为空",L"GDMPLab",L"2024-03-30");

    IUiView* pUIView = pUiDocViewMgr->GetCurrentUiView();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pUIView != nullptr, L"当前没有活动的视图",L"GDMPLab",L"2024-03-30");
    IUiDocument* pUIDoc = pUIView->GetUiDocument();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pUIDoc != nullptr, L"pUIDoc不能为空",L"GDMPLab",L"2024-03-30");
    gcmp::IDocument* pDocument = pUIDoc->GetDbDocument();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDocument, L"Active Document为空",L"GDMPLab",L"2024-03-30");

    if (!DEBUG_MODE(RemoveReadonlyWithNoTransactionAndNoSave) && pDocument->IsReadonlyWithNoTransactionAndNoSave())
    {
        UiCommonDialog::ShowMessageBox(GBMP_TR(L"保存文档"), GBMP_TR(L"文件以只读模式打开，不能另存为"), (int)UiCommonDialog::ButtonType::OK);
        return nullptr;
    }
    //优先执行文档修复
    if (DEBUG_MODE(EnableFixInvalidDoc))
    {
        OwnerPtr<IUserTransaction> opFixTransaction = IUserTransaction::Create(pDocument, GBMP_TR(L"损坏文档修复"));
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(opFixTransaction, L"事务创建失败",L"GDMPLab",L"2024-03-30");
        std::wstring fixReport;
        bool bFixed = DocumentValidationUtils::FixInvalidDocument(pDocument, fixReport);
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(bFixed, GBMP_TR(L"文档修复（失败）! ") + fixReport,L"GDMPLab",L"2024-03-30");
        if (bFixed)
        {
            bool bCommit = opFixTransaction->Commit();
            DBG_WARN_AND_RETURN_NULLPTR_UNLESS(bCommit, L"事务提交失败",L"GDMPLab",L"2024-03-30");
        }
        else
        {
            bool bRollback = opFixTransaction->Rollback();
            DBG_WARN_AND_RETURN_NULLPTR_UNLESS(bRollback, L"事务回滚失败",L"GDMPLab",L"2024-03-30");
        }
    }
    //文档有效性检测
    {
        std::wstring checkReport;
        bool ret = DocumentValidationUtils::ValidateDocumentStatus(pDocument, checkReport);

        if (!ret)
        {
            UiCommonDialog::ButtonType rt = UiCommonDialog::ShowMessageBox(GBMP_TR(L"文档状态检测（失败）"), checkReport + GBMP_TR(L"\n是否仍然保存？"), (int)UiCommonDialog::ButtonType::Yes | (int)UiCommonDialog::ButtonType::No);
            if (rt != UiCommonDialog::ButtonType::Yes)
            {
                return nullptr;
            }
        }
    }

    std::wstring filePathName;
    const int nCmdParamsCnt = (int)cmdParams.size();
    if (nCmdParamsCnt == 0)
    {
        {
            const GbmpString& defaultFolder = LogManager::Get()->GetLogsFolder();
            std::wstring filter = std::wstring(L"Project(*") + GDMPLAB_FILE_EXT + L")";
            filePathName = UiCommonDialog::ShowSaveFileDialog(GBMP_TR(L"另存工程"), defaultFolder.getString(), filter);
        }

        if (filePathName.empty())
        {
            return nullptr;
        }
    }
    else if (nCmdParamsCnt == 1)
    {
        // 回放时，需要把文件存入相对于Log目录的地方
        auto itor = cmdParams.find(L"FilePath");
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(itor != cmdParams.end(), L"所需的参数FilePath不存在",L"GDMPLab",L"2024-03-30");
        filePathName = gcmp::LogManager::Get()->GetAbsolutePathForLog(itor->second.AsWString());
    }
    else
    {
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(false, L"SaveFileAsCmd的参数个数应该为0或1",L"GDMPLab",L"2024-03-30");
    }

    if (!filePathName.empty())
    {
        // 弹出所有Action。
        std::wstring currentCmdID;
        IAction* pCurrentAction = IActionManager::CurrentAction();
        if (pCurrentAction)
        {
            currentCmdID = pCurrentAction->GetCommandId();
            IActionManager::Reset();
        }
        DocumentSaveOptions saveOptions(true);
        DocumentSaveResult saveResult;
        pDocument->SaveAs(filePathName, saveOptions, saveResult);
        if (DocumentSaveError::Ok != saveResult.Code)
        {
            UiCommonDialog::ShowMessageBox(GBMP_TR(L"另存文档错误"), SaveFileCmd::GetSaveErrorMessage((gcmp::DocumentSaveError)saveResult.Code), (int)UiCommonDialog::ButtonType::OK);
        }

        //更新文档名称,并激活文档标题更新
        pUiDocViewMgr->ActivateUiView(pUIView, true);


        // 保存完文件后需要恢复action。
        if (currentCmdID.size() > 0)
        {
            ICommandManager::Get()->SendCommand(currentCmdID);
        }
    }

    return nullptr;
}

bool SaveFileAsCmd::IsEnabled() const
{
    if (SaveFileCmd::IsInProfileFamilyEnvironment())
    {
        return true;
    }
    return GcmpCommandState::IsInDocumentEnvironment()
        && !GcmpCommandState::IsInInPlaceEditMode()
        && !GcmpCommandState::IsInEditMode()
        && !GcmpCommandState::IsInAnimationEnvironment();
}

bool SaveFileAsCmd::IsVisible() const
{
    return GcmpCommandState::IsInDocumentEnvironment() && !GcmpCommandState::IsInAnimationEnvironment();
}

SaveFileAsCmd::SaveFileAsCmd() :CommandBase(ID_CMD_SAVE_FILE_AS, true)
{

}
REGISTER_GM_COMMAND(SaveFileAsCmd)


